// Copyright (c) MatrixFramework. All rights reserved.
// Licensed under the MIT License. See LICENSE in the project root for license information.

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Matrix.ServiceCommunication.Services;

namespace Matrix.ServiceCommunication.Monitoring;

/// <summary>
/// HTTP客户端拦截器，用于收集指标和链路追踪
/// </summary>
public class HttpClientInterceptor : DelegatingHandler
{
    private readonly IServiceCommunicationMetrics _metrics;
    private readonly ILogger<HttpClientInterceptor> _logger;

    public HttpClientInterceptor(
        IServiceCommunicationMetrics metrics,
        ILogger<HttpClientInterceptor> logger)
    {
        _metrics = metrics ?? throw new ArgumentNullException(nameof(metrics));
        _logger = logger ?? throw new ArgumentNullException(nameof(logger));
    }

    protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
        var serviceName = ExtractServiceName(request);
        var activityName = $"HTTP {request.Method} {serviceName}";
        var operationName = $"{request.Method.Method} {request.RequestUri?.PathAndQuery}";

        // 开始Activity用于链路追踪
        using var activity = _metrics.StartActivity(activityName, serviceName, operationName);
        var stopwatch = Stopwatch.StartNew();

        try
        {
            // 增加活跃请求计数
            _metrics.IncrementActiveRequests(serviceName);

            // 添加Activity标签
            if (activity != null)
            {
                _metrics.SetActivityTags(activity,
                    ("http.method", request.Method.Method),
                    ("http.url", request.RequestUri?.ToString()),
                    ("service.target", serviceName),
                    ("http.request.id", request.Headers.Contains("X-Request-Id")
                        ? request.Headers.GetValues("X-Request-Id").FirstOrDefault()
                        : Guid.NewGuid().ToString()));

                // 添加用户上下文信息到Activity
                if (request.Headers.Contains("X-User-Id"))
                {
                    activity.SetTag("user.id", request.Headers.GetValues("X-User-Id").FirstOrDefault());
                }

                if (request.Headers.Contains("X-Tenant-Id"))
                {
                    activity.SetTag("tenant.id", request.Headers.GetValues("X-Tenant-Id").FirstOrDefault());
                }

                if (request.Headers.Contains("X-Trace-Id"))
                {
                    activity.SetTag("trace.id", request.Headers.GetValues("X-Trace-Id").FirstOrDefault());
                }
            }

            // 添加自定义请求头用于追踪
            if (request.Headers.Contains("X-Request-Id"))
            {
                activity?.SetTag("http.request.id",
                    request.Headers.GetValues("X-Request-Id").FirstOrDefault());
            }

            _logger.LogDebug("发送HTTP请求: {Method} {Url} [RequestId: {RequestId}]",
                request.Method, request.RequestUri,
                request.Headers.Contains("X-Request-Id")
                    ? request.Headers.GetValues("X-Request-Id").FirstOrDefault()
                    : "N/A");

            // 发送请求
            var response = await base.SendAsync(request, cancellationToken);
            stopwatch.Stop();

            // 记录指标
            var duration = stopwatch.Elapsed.TotalMilliseconds;
            _metrics.RecordRequest(serviceName, request.Method.Method, (int)response.StatusCode, duration);

            // 更新Activity信息
            if (activity != null)
            {
                _metrics.SetActivityTags(activity,
                    ("http.response.status_code", response.StatusCode.ToString()),
                    ("http.response.status_class", GetStatusClass((int)response.StatusCode)),
                    ("http.response.size", response.Content?.Headers?.ContentLength?.ToString() ?? "unknown"));

                if (!response.IsSuccessStatusCode)
                {
                    activity.SetStatus(ActivityStatusCode.Error, $"HTTP {(int)response.StatusCode}");
                }
                else
                {
                    activity.SetStatus(ActivityStatusCode.Ok);
                }

                // 添加响应头信息
                if (response.Headers.Contains("X-Response-Time"))
                {
                    activity.SetTag("server.response.time_ms",
                        response.Headers.GetValues("X-Response-Time").FirstOrDefault());
                }
            }

            // 记录成功日志
            _logger.LogDebug("HTTP请求完成: {Method} {Url} -> {StatusCode} {Duration}ms",
                request.Method, request.RequestUri, response.StatusCode, duration);

            return response;
        }
        catch (Exception ex)
        {
            stopwatch.Stop();

            // 记录错误指标
            var duration = stopwatch.Elapsed.TotalMilliseconds;
            _metrics.RecordRequest(serviceName, request.Method.Method, 500, duration);

            // 更新Activity状态
            if (activity != null)
            {
                activity.SetStatus(ActivityStatusCode.Error, ex.Message);
                activity.SetTag("error.type", ex.GetType().Name);
                activity.SetTag("error.message", ex.Message);
            }

            _logger.LogError(ex, "HTTP请求异常: {Method} {Url} -> {Error} {Duration}ms",
                request.Method, request.RequestUri, ex.Message, duration);

            throw;
        }
        finally
        {
            // 减少活跃请求计数
            _metrics.DecrementActiveRequests(serviceName);

            // 结束Activity
            if (activity != null)
            {
                activity.SetTag("http.request.duration_ms", stopwatch.Elapsed.TotalMilliseconds);
            }
        }
    }

    private static string ExtractServiceName(HttpRequestMessage request)
    {
        // 从请求头中获取服务名称
        if (request.Headers.Contains("X-Service-Name"))
        {
            return request.Headers.GetValues("X-Service-Name").FirstOrDefault() ?? "unknown";
        }

        // 从URL中推断服务名称
        var host = request.RequestUri?.Host;
        var path = request.RequestUri?.AbsolutePath;

        if (!string.IsNullOrEmpty(host) && !string.IsNullOrEmpty(path))
        {
            // 例如：http://auth-service/api/users -> auth-service
            if (host.Contains("-service") || host.Contains("service"))
            {
                return host.Split(':')[0]; // 移除端口号
            }

            // 从路径中推断
            var pathSegments = path?.Split('/', StringSplitOptions.RemoveEmptyEntries);
            if (pathSegments?.Length > 0)
            {
                return pathSegments[0];
            }
        }

        return "unknown";
    }

    private static string GetStatusClass(int statusCode)
    {
        return statusCode switch
        {
            >= 200 and < 300 => "2xx",
            >= 300 and < 400 => "3xx",
            >= 400 and < 500 => "4xx",
            >= 500 => "5xx",
            _ => "unknown"
        };
    }
}

/// <summary>
/// HTTP客户端拦截器扩展方法
/// </summary>
public static class HttpClientInterceptorExtensions
{
    /// <summary>
    /// 添加HTTP客户端拦截器
    /// </summary>
    /// <param name="builder">HTTP客户端构建器</param>
    /// <param name="metrics">指标收集器</param>
    /// <param name="logger">日志记录器</param>
    /// <returns>HTTP客户端构建器</returns>
    public static IHttpClientBuilder AddHttpInterception(
        this IHttpClientBuilder builder,
        IServiceCommunicationMetrics metrics,
        ILogger<HttpClientInterceptor> logger)
    {
        return builder.AddHttpMessageHandler(() => new HttpClientInterceptor(metrics, logger));
    }
}